package com.yanxx.codegenerator.impl;

import com.yanxx.codegenerator.CodeGenerator;
import com.yanxx.codegenerator.format.CodeFormatter;
import com.yanxx.codegenerator.format.impl.SimpleCodeFormatter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 顺序编码生成器实现
 * 保证生成的编号是连续的，并支持回收未使用的编号
 */
public class SequentialCodeGenerator implements CodeGenerator {
    private static final Logger logger = LoggerFactory.getLogger(SequentialCodeGenerator.class);
    
    // 编号前缀
    private final String prefix;
    
    // 编号长度（不包括前缀）
    private final int codeLength;
    
    // 当前最大编号值
    protected final AtomicLong currentMaxValue;
    
    // 已确认使用的编号集合
    protected final Set<String> confirmedCodes;
    
    // 待回收的编号集合（已生成但未确认使用）
    protected final Set<String> pendingCodes;
    
    // 回收的编号集合（可重新使用）
    protected final ConcurrentSkipListSet<String> recycledCodes;
    
    // 读写锁，保证线程安全
    private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    
    // 编码格式化器
    private final CodeFormatter formatter;
    
    /**
     * 构造函数
     *
     * @param prefix     编号前缀
     * @param codeLength 编号长度（不包括前缀）
     * @param startValue 起始编号值
     */
    public SequentialCodeGenerator(String prefix, int codeLength, long startValue) {
        this.prefix = prefix != null ? prefix : "";
        this.codeLength = codeLength;
        this.currentMaxValue = new AtomicLong(startValue);
        this.confirmedCodes = Collections.newSetFromMap(new ConcurrentHashMap<>());
        this.pendingCodes = Collections.newSetFromMap(new ConcurrentHashMap<>());
        this.recycledCodes = new ConcurrentSkipListSet<>();
        this.formatter = new SimpleCodeFormatter(prefix, codeLength);
    }
    
    /**
     * 构造函数，使用自定义格式化器
     *
     * @param startValue 起始编号值
     * @param formatter  编码格式化器
     */
    public SequentialCodeGenerator(long startValue, CodeFormatter formatter) {
        this.prefix = "";
        this.codeLength = 0;  // 由格式化器决定
        this.currentMaxValue = new AtomicLong(startValue);
        this.confirmedCodes = Collections.newSetFromMap(new ConcurrentHashMap<>());
        this.pendingCodes = Collections.newSetFromMap(new ConcurrentHashMap<>());
        this.recycledCodes = new ConcurrentSkipListSet<>();
        this.formatter = formatter;
    }
    
    /**
     * 构造函数，使用简单格式化器
     *
     * @param startValue 起始编号值
     * @param prefix     前缀
     * @param length     编号长度
     */
    public SequentialCodeGenerator(long startValue, String prefix, int length) {
        this(startValue, new SimpleCodeFormatter(prefix, length));
    }
    
    /**
     * 默认构造函数，使用默认配置
     */
    public SequentialCodeGenerator() {
        this("", 6, 0);
    }
    
    @Override
    public String generate() {
        // 优先使用回收的编号
        String recycledCode = getRecycledCode();
        if (recycledCode != null) {
            pendingCodes.add(recycledCode);
            logger.debug("Generated recycled code: {}", recycledCode);
            return recycledCode;
        }
        
        // 生成新编号
        String newCode = generateNewCode();
        pendingCodes.add(newCode);
        logger.debug("Generated new code: {}", newCode);
        return newCode;
    }
    
    @Override
    public boolean recycle(String code) {
        if (code == null || code.isEmpty()) {
            logger.warn("Cannot recycle null or empty code");
            return false;
        }
        
        lock.writeLock().lock();
        try {
            // 检查编号是否已确认使用
            if (confirmedCodes.contains(code)) {
                logger.warn("Cannot recycle confirmed code: {}", code);
                return false;
            }
            
            // 从待回收集合中移除
            boolean removed = pendingCodes.remove(code);
            if (removed) {
                // 添加到回收集合中
                recycledCodes.add(code);
                logger.debug("Recycled code: {}", code);
                return true;
            } else {
                logger.warn("Code not found in pending codes: {}", code);
                return false;
            }
        } finally {
            lock.writeLock().unlock();
        }
    }
    
    @Override
    public boolean confirm(String code) {
        if (code == null || code.isEmpty()) {
            logger.warn("Cannot confirm null or empty code");
            return false;
        }
        
        lock.writeLock().lock();
        try {
            // 检查编号是否已生成
            if (!pendingCodes.contains(code)) {
                logger.warn("Cannot confirm code that is not generated: {}", code);
                return false;
            }
            
            // 从待回收集合中移除
            pendingCodes.remove(code);
            // 添加到已确认集合中
            confirmedCodes.add(code);
            logger.debug("Confirmed code: {}", code);
            return true;
        } finally {
            lock.writeLock().unlock();
        }
    }
    
    @Override
    public int getAvailableCount() {
        return recycledCodes.size();
    }
    
    @Override
    public void initialize() {
        logger.info("Initializing SequentialCodeGenerator with prefix: {}, codeLength: {}", prefix, codeLength);
        // 子类可以重写此方法，加载持久化的编号数据
    }
    
    @Override
    public void shutdown() {
        logger.info("Shutting down SequentialCodeGenerator");
        // 子类可以重写此方法，持久化编号数据
    }
    
    /**
     * 获取回收的编号
     *
     * @return 回收的编号，如果没有则返回null
     */
    private String getRecycledCode() {
        lock.readLock().lock();
        try {
            if (recycledCodes.isEmpty()) {
                return null;
            }
            
            // 获取并移除第一个回收的编号
            String code = recycledCodes.first();
            recycledCodes.remove(code);
            return code;
        } finally {
            lock.readLock().unlock();
        }
    }
    
    /**
     * 生成新的编号
     *
     * @return 新生成的编号
     */
    private String generateNewCode() {
        long value = currentMaxValue.incrementAndGet();
        return formatter.format(value);
    }
    

    
    /**
     * 获取当前所有待回收的编号
     *
     * @return 待回收的编号集合
     */
    public Set<String> getPendingCodes() {
        lock.readLock().lock();
        try {
            return new HashSet<>(pendingCodes);
        } finally {
            lock.readLock().unlock();
        }
    }
    
    /**
     * 获取当前所有已确认的编号
     *
     * @return 已确认的编号集合
     */
    public Set<String> getConfirmedCodes() {
        lock.readLock().lock();
        try {
            return new HashSet<>(confirmedCodes);
        } finally {
            lock.readLock().unlock();
        }
    }
    
    /**
     * 获取当前所有回收的编号
     *
     * @return 回收的编号集合
     */
    public Set<String> getRecycledCodes() {
        lock.readLock().lock();
        try {
            return new HashSet<>(recycledCodes);
        } finally {
            lock.readLock().unlock();
        }
    }
    
    /**
     * 设置当前最大值
     *
     * @param value 新的最大值
     */
    protected void setCurrentMaxValue(long value) {
        currentMaxValue.set(value);
    }
    
    /**
     * 获取当前最大值
     *
     * @return 当前最大值
     */
    protected long getCurrentMaxValue() {
        return currentMaxValue.get();
    }
    
    /**
     * 获取格式化器
     *
     * @return 编码格式化器
     */
    protected CodeFormatter getFormatter() {
        return formatter;
    }
}